import { defineStore } from 'pinia'

export interface ContourSegment {
  start: { x: number; y: number }
  end: { x: number; y: number }
}

export type ExpressionStatus = 'idle' | 'evaluating' | 'ready' | 'error'

export interface ExpressionEntry {
  id: string
  expression: string
  color: string
  visible: boolean
  status: ExpressionStatus
  errorMessage: string | null
  sampleValue: number | null
  segments: ContourSegment[]
  segmentCount: number
  lastComputedAt: number | null
  lastDurationMs: number | null
  cacheHit: boolean
  validSampleRatio: number | null
}


export interface UpdatePayload {
  id: string
  expression?: string
  color?: string
  visible?: boolean
}

const defaultColors = [
  '#f97316',
  '#22d3ee',
  '#a855f7',
  '#facc15',
  '#38bdf8',
  '#4ade80',
  '#fb7185',
] as const

let expressionCounter = 0

function nextColor(index: number): string {
  return defaultColors[index % defaultColors.length] ?? '#38bdf8'
}

function nextId(): string {
  expressionCounter += 1
  return `expr-${Date.now()}-${expressionCounter}`
}

export const useExpressionStore = defineStore('expressions', {
  state: () => ({
    expressions: [] as ExpressionEntry[],
  }),
  getters: {
    visibleExpressions(state): ExpressionEntry[] {
      return state.expressions.filter((entry) => entry.visible)
    },
  },
  actions: {
    initialiseDefaults() {
      if (this.expressions.length === 0) {
        this.addExpression('x^2 + y^2 = 1')
      }
    },
    addExpression(expression = '') {
      const id = nextId()
      const color = nextColor(this.expressions.length)
      this.expressions.push({
        id,
        expression,
        color,
        visible: true,
        status: 'idle',
        errorMessage: null,
        sampleValue: null,
        segments: [],
        segmentCount: 0,
        lastComputedAt: null,
        lastDurationMs: null,
        cacheHit: false,
        validSampleRatio: null,
      })
    },
    removeExpression(id: string) {
      this.expressions = this.expressions.filter((entry) => entry.id !== id)
    },
    updateExpression(payload: UpdatePayload) {
      const entry = this.expressions.find((item) => item.id === payload.id)
      if (!entry) {
        return
      }
      if (payload.expression !== undefined) {
        entry.expression = payload.expression
      }
      if (payload.color !== undefined) {
        entry.color = payload.color
      }
      if (payload.visible !== undefined) {
        entry.visible = payload.visible
      }
    },
    markEvaluating(ids: string[]) {
      ids.forEach((id) => {
        const entry = this.expressions.find((item) => item.id === id)
        if (entry) {
          entry.status = 'evaluating'
          entry.errorMessage = null
          entry.cacheHit = false
        }
      })
    },
    setResult(
      id: string,
      payload: {
        segments: ContourSegment[]
        sampleValue: number | null
        durationMs: number
        cacheHit: boolean
        validSampleRatio?: number | null
      },
    ) {
      const entry = this.expressions.find((item) => item.id === id)
      if (!entry) {
        return
      }
      entry.status = 'ready'
      entry.errorMessage = null
      entry.sampleValue = payload.sampleValue
      entry.segments = payload.segments
      entry.segmentCount = payload.segments.length
      entry.lastComputedAt = Date.now()
      entry.lastDurationMs = payload.durationMs
      entry.cacheHit = payload.cacheHit
      entry.validSampleRatio = payload.validSampleRatio ?? null
    },
    setError(id: string, errorMessage: string) {
      const entry = this.expressions.find((item) => item.id === id)
      if (!entry) {
        return
      }
      entry.status = 'error'
      entry.errorMessage = errorMessage
      entry.sampleValue = null
      entry.segments = []
      entry.segmentCount = 0
      entry.cacheHit = false
      entry.validSampleRatio = null
    },
    clearSegments() {
      this.expressions.forEach((entry) => {
        entry.segments = []
        entry.segmentCount = 0
        entry.validSampleRatio = null
      })
    },
  },
})
